package benchmark;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;


public class FSByteBuffer extends AbstractMTTask {

	private class FSByteBufferCallable implements Callable<String> {
		
		ByteBuffer buffer;
		int position;
		
		public FSByteBufferCallable(ByteBuffer buffer, int position) {
			this.buffer = buffer;
			this.position = position;
		}
		
		@Override
		public String call() throws Exception {
			long counter = iterTime;
			while (counter-- > 0) {
				buffer.putLong(position, buffer.getLong(position) + counter);
			}
			// 
			// return sum of the entire array to avoid optimize
			long sum = 0;
			for (int i = 0; i < buffer.capacity(); i++) {
				sum += buffer.get(i);
			}
			return Long.toString(sum);

//			return String.format("array[%d] == %d", position, buffer.getLong(position));
		}
		
	}
	
	private volatile ByteBuffer buffer;
	
	private static final int ELEMENT_SIZE = 8;
	
	long iterTime;


	/* 
	 * @param param
	 * 0. class name
	 * 1. thread number
	 * 2. stride
	 * 3. iteration time
	 */
	@Override
	protected List<Callable<String>> initCallables(List<String> param) {
		int stride = Integer.parseInt(param.get(2)) * ELEMENT_SIZE;
		iterTime = Long.parseLong(param.get(3));
		
		buffer = ByteBuffer.allocateDirect(stride * threadNum);
		
		for (int i = 0; i < stride; i += ELEMENT_SIZE) {
			buffer.putLong(i, i);
		}
		
		List<Callable<String>> l = new ArrayList<Callable<String>>();
		for (int i = 0; i < this.threadNum; i++) {
			l.add(new FSByteBufferCallable(buffer, stride * i));
		}
		return l;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
